package cn.itsource.ymcc.mq;

import cn.itsource.ymcc.constants.BaseConstants;
import cn.itsource.ymcc.domain.PayFlow;
import cn.itsource.ymcc.dto.AlipayNotifyDto;
import cn.itsource.ymcc.service.IPayFlowService;
import cn.itsource.ymcc.util.AssertUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
//支付事务组
@RocketMQTransactionListener(txProducerGroup = BaseConstants.PayMQ.TX_PAY_RESULT_GROUP)
@Slf4j
public class PayFlowSaveTransactionListener implements RocketMQLocalTransactionListener {

    @Autowired
    private IPayFlowService payFlowService;

    //执行本地事务
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {

        try{

            AssertUtil.isNotNull(arg,"无效的订单数据");

            Map<String,String> args = (Map<String, String>) arg;
            String saveFlow = args.get("SaveFlow");

            AssertUtil.isNotEmpty(saveFlow,"无效的SaveFlow参数");
            log.info("尝试保存支付流水，执行本地事务.{}",msg);

            //防止重复保存
            if(saveFlow.equals("true")){
                //多个事务消息，只有第一个消息才保持订单，防止重复下单
                byte[] payload = (byte[]) msg.getPayload();

                String json = new String(payload, "utf-8");
                log.info("保存支付流水，执行本地事务.{}",json);
                //保存支付账单
                AlipayNotifyDto alipayNotifyDto = JSON.parseObject(json,AlipayNotifyDto.class);

                //幂等处理 ， 如果做了集群，要使用分布式锁
                synchronized (alipayNotifyDto.getOut_trade_no()){
                    //幂等处理
                    PayFlow payFlow = payFlowService.selectByOutTradeNo((alipayNotifyDto.getOut_trade_no()));
                    if(payFlow == null){
                        //保存订单到数据库
                        payFlowService.create(alipayNotifyDto);
                    }
                }
            }

            //消息推送，直接返回TRUE
            return RocketMQLocalTransactionState.COMMIT;

        }catch (Exception e){
            e.printStackTrace();
        }

        return RocketMQLocalTransactionState.ROLLBACK;
    }

    //检查本地事务状态
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        byte[] payload = (byte[]) msg.getPayload();
        try{
            String json = new String(payload, "utf-8");

            log.info("保存支付流水，回查本地事务.{}",json);
            //保存支付账单
            AlipayNotifyDto alipayNotifyDto = JSON.parseObject(json,AlipayNotifyDto.class);

            PayFlow order = payFlowService.selectByOutTradeNo(alipayNotifyDto.getOut_trade_no());
            //回查订单状态
            if(order != null){
                return RocketMQLocalTransactionState.COMMIT;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return RocketMQLocalTransactionState.ROLLBACK;
    }
}
